﻿using ICSharpCode.TextEditor.Document;
using SharpTools.Common;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml.Linq;

namespace SharpTools.Forms
{
    public partial class EntityForm : DockContentForm
    {
        public EntityForm()
        {
            InitializeComponent();
            txtEntitySharpCode.ShowEOLMarkers = false;
            txtEntitySharpCode.ShowHRuler = false;
            txtEntitySharpCode.ShowInvalidLines = false;
            txtEntitySharpCode.ShowMatchingBracket = true;
            txtEntitySharpCode.ShowSpaces = false;
            txtEntitySharpCode.ShowTabs = false;
            txtEntitySharpCode.ShowVRuler = false;
            txtEntitySharpCode.AllowCaretBeyondEOL = false;
            txtEntitySharpCode.Document.HighlightingStrategy = HighlightingStrategyFactory.CreateHighlightingStrategy("C#");
            txtEntitySharpCode.Encoding = Encoding.GetEncoding("GB2312");
            
            ///初始化 类型对应键值对集合
            InitTypeName();
        }

        private void EntityForm_Load(object sender, EventArgs e)
        {
            cboNameType.SelectedIndex = 0;
            InitBuilderCode();
        }


        private void InitBuilderCode()
        {
            DB db = new DB(ConnectionModel.DbType, ConnectionModel.ConnectionString);
            DBInfo dbInfo = db.Info;
            var lstCol = dbInfo.GetAllColumnInfo(TableName);

            StringPlus strPuls = new StringPlus();
            strPuls.AppendLine(UsingNameSpaceString());
            strPuls.AppendLine();
            strPuls.AppendLine(string.Format("namespace {0}", dbInfo.DBName.ToFormat(cboNameType.SelectedItem)));
            strPuls.AppendLine("{");

            string tabNameDesc = dbInfo.GetTableComment(TableName);

            if (!string.IsNullOrWhiteSpace(tabNameDesc))
            {
                strPuls.AppendSpaceLine(1, "/// <summary>");
                strPuls.AppendSpaceLine(1, string.Format("/// {0}", tabNameDesc));
                strPuls.AppendSpaceLine(1, "/// </summary>");
            }
            if (CK_DataContract.Checked)
            {
                strPuls.AppendSpaceLine(1, "[DataContract]");
            }
            if (CK_DisplayName.Checked)
            {
                strPuls.AppendSpaceLine(1, string.Format("[DisplayName(\"{0}\")]", tabNameDesc));
            }
            if (CK_Serializable.Checked)
            {
                strPuls.AppendSpaceLine(1, "[Serializable]");
            }
            strPuls.AppendSpaceLine(1, string.Format("public partial class {0}", TableName.ToFormat(cboNameType.SelectedItem)));
            strPuls.AppendSpaceLine(1, "{");

            #region 构造函数及属性默认值

            strPuls.AppendSpaceLine(2, string.Format("public {0}()", TableName.ToFormat(cboNameType.SelectedItem)));
            strPuls.AppendSpaceLine(2, "{");

            foreach (var col in lstCol)
            {
                if (!string.IsNullOrWhiteSpace(col.DefaultVal))
                {
                    string val = string.Empty;
                    if (dictTypeName[col.TypeName].Equals("string", StringComparison.OrdinalIgnoreCase))
                    {
                        val = "\"" + col.DefaultVal.Replace("(", "").Replace(")", "") + "\"";
                    }
                    else
                    {
                        val = col.DefaultVal.Replace("(", "").Replace(")", "");
                    }
                    strPuls.AppendSpaceLine(3, string.Format("this.{0} = {1};", col.ColumnName.ToFormat(cboNameType.SelectedItem), val));
                }
            }
            strPuls.AppendSpaceLine(2, "}");

            #endregion

            strPuls.AppendLine();

            #region 属性
            foreach (var col in lstCol)
            {
                if (!string.IsNullOrWhiteSpace(col.DeText))
                {
                    strPuls.AppendSpaceLine(2, "/// <summary>");
                    strPuls.AppendSpaceLine(2, string.Format("/// {0}", col.DeText));
                    strPuls.AppendSpaceLine(2, "/// </summary>");
                }
                if (CK_DisplayName.Checked)
                {
                    strPuls.AppendSpaceLine(2, string.Format("[DisplayName(\"{0}\")]", col.DeText));
                }
                if (CK_DataContract.Checked)
                {
                    strPuls.AppendSpaceLine(2, "[DataMember]");
                }
                string colTypeName = dictTypeName[col.TypeName];
                if (col.CanNull && !dictTypeName[col.TypeName].Equals("string", StringComparison.OrdinalIgnoreCase))
                {
                    colTypeName = colTypeName + "?";
                }
                strPuls.AppendSpaceLine(2, string.Format("public {0} {1} {2}", colTypeName, col.ColumnName.ToFormat(cboNameType.SelectedItem), "{ get;set; }"));
                strPuls.AppendLine();
            }
            #endregion

            strPuls.AppendSpaceLine(1, "}");
            strPuls.AppendLine("}");

            string codeText = strPuls.ToString();

            txtEntitySharpCode.Text = codeText;
        }

        /// <summary>
        /// 实体默认的命名空间
        /// </summary>
        /// <returns></returns>
        string UsingNameSpaceString()
        {
            List<string> lstNameSpace = new List<string>()
            {
                "using System;",
                "using System.Collections.Generic;",
                "using System.Linq;",
                "using System.Text;",
            };

            if (CK_DisplayName.Checked)
            {
                lstNameSpace.Add("using System.ComponentModel;");
            }
            if (CK_DataContract.Checked)
            {
                lstNameSpace.Add("using System.Runtime.Serialization;");
            }
            string res = string.Join("\r\n", lstNameSpace);
            return res;
        }

        /// <summary>
        /// 初始化 类型对应
        /// </summary>
        Dictionary<string, string> dictTypeName = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
        void InitTypeName()
        {
            string csType = string.Empty;
            string dbtype_config = Path.GetFullPath("..\\..\\config\\dbtype.xml");
            if (File.Exists(dbtype_config))
            {
                XElement xml = XElement.Load(dbtype_config);
                var eles = xml.Elements();
                foreach (var ele in eles)
                {
                    string attVal1 = ele.Attribute("dbtype").Value;
                    string attVal2 = ele.Attribute("cstype").Value;
                    dictTypeName[attVal1] = attVal2;
                }
            }
        }

        private void CK_Serializable_CheckedChanged(object sender, EventArgs e)
        {
            InitBuilderCode();
        }

        private void cboNameType_SelectedIndexChanged(object sender, EventArgs e)
        {
            InitBuilderCode();
        }
    }


    public static class StringExt
    {
        public static string ToFormat(this string value, object type)
        {
            switch (type.ToString())
            {
                case "默认格式":
                    return value;
                case "全部大写":
                    return value.ToUpper();
                case "首字母大写":                   
                    return value.ToUpperFirstword();
                case "全部小写":
                    return value.ToLower();
                default:
                    return value;
            }
        }
    }
}
